/*
 *  body.h
 *  EPPI-0.0
 *
 *  Created by Juan Carlos Garcia Orden on 15/11/07.
 *
 */
 
#ifndef _body_h_
#define _body_h_

#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <algorithm>
#include <string>
#include "COMPONENTS/component.h"
#include "point.h"
#include "COMPONENTS/cload.h"
#include "COMPONENTS/ctload.h"
#include "COMPONENTS/iacload.h"
#include "GEOMETRY/surface.h"

using namespace std;

class MecSystem;
class Component;
class sparseMatrix;

extern int rankk;

class Body
{
public:
	string name;
	string type;
	int dim;								/** Space dimension */
	MecSystem* parentSystem;				/** Parent system */
	vector<Component*> vComponents;			/** Vector of components */
	vector<Component*> vLoads;				/** Vector of loads */
	vector<string> vPointNamesSurface;	 // Names of the nodes on the surface (without /systemName)
	vector<Point*> vPPointSurface;		// Pointers to surface points
	map<string,int,less<string> > pNamePNumber;	/** table of Name - number of surface points (needed by vtu format) */
	string outGraphFilex;
	ofstream localFGraph;
	Surface *surface; 
	string surfName;
//	vector<vector<double> > vLocalPoints;	// Local points, for joints and contact. Local reference
	bool contactAllOption;
	bool contactFileOption;
	bool contactNamesOption;
	vector<double> localSystem;	// Global coordinates of body points for ground
	vector<string> vPointNamesContact;
	//vector<string>* vPointNamesContact;	 // Names of the nodes for contact (without /systemName)
	//vector<Point*>* vPPointContact;		// Pointers to contact points
		

public:	
	Body();
	Body(ifstream &, string, MecSystem*);
	virtual ~Body(){}
	
	void setDofs();							/** Set degrees of freedom from its components */
	void setLocalGlob();					/** Set local-global numbering on components */
	void setLoad(string, ifstream &, const vector<double> &vTime, const map<string,vector<string>,less<string> >*);		// edit /** Set concentrated load */
	void reportLoads();
	void reportContent();
	void initializeGlobalDofs(vector<double> &, vector<double> &, double &);

	void fillResidual(vector<double>& res_in,
					  vector<double>& q_in,
  					  vector<double>& dq_in,
					  const double& time, const int&, const double&, const int&, const double&);
	
	void fillResidual(vector<double>& residue,
					  const vector<double>& q,
					  const vector<double>& qdot,
					  const vector<double>& qddot,
					  const double& time,
					  const int&,
					  const double&, const int&,
  					  const int&,
					  const double&
					  );
	void fillResFi(	vector<double>& residue,
				   const vector<double>& q,
				   const vector<double>& qddot,
				   const int&
				   );
	void fillResFq(	vector<double>& residue,
				   const vector<double>& q,
				   const vector<double>& qdot,
				   const int&,
   				   const int&,
				   const double&
				   );
	void fillResFt(	vector<double>& residue,
				   const double& time,
				   const int&,
				   const double&, const int&
				   );
//	void fillTangent(sparseMatrix&, vector<double>&, const double& time, const int&);

	void fillTangent(sparseMatrix&, vector<vector<double> >&, vector<vector<double> >&, vector<vector<double> >&, 
					 vector<int>&, vector<int>&,
					 vector<double>&, vector<double>&,
					 const double& time, const int&);
/*	
	void fillTangent(	sparseMatrix& tangent,
					 const vector<double>& q,
					 const vector<double>& qdot,
					 const vector<double>& qddot,
					 double partial_qdot,
					 double partial_qddot,
					 const double& time,
					 const int&,
 					 const int&,
					 const double& 
					 );
*/
	void fillTangent(sparseMatrix&, vector<vector<double> >&, vector<vector<double> >&, vector<vector<double> >&,
					 vector<int>&, vector<int>&,	
					 const vector<double>& q,
					 const vector<double>& qdot,
					 const vector<double>& qddot,
					 double partial_qdot,
					 double partial_qddot,
					 const double& time,
					 const int&,
 					 const int&,
					 const double& 
					 );	
	void fillMassMatrix(sparseMatrix& Ma, const vector<double>& q, const double& time );
	
	void fillMassMatrix(vector<double>& vMa, const vector<double>& q, const double& time );

	void fillForce(	vector<double>& f,
				   const vector<double>& q,
				   const vector<double>& qdot,
				   const double& time,
				   const double&, const int&
				   );
	
	void setSparsePattern(vector< vector<int> >&);
	void setSparsePatternInertia(vector< vector<int> >&);
	void changePointName(string&, string&);

	// edit
//	void updateTimeStep(const int&);	// edit: set current timestep in forces ....
        void writeFileGraph(ofstream&,string&,string&,string&, bool&, bool&, bool&);	/** Write graphical output to file */
	void initializeCompRes(const bool&, const double&, const int&);
//	void initializeCompTang(const bool&, const bool&);
	void initializeCompTang(const bool&);
	void calcEner(double&, double&, double&, double&, double&, double&, double&, int&, vector<double>&, vector<double>&);
	void calcEntropy(double&, double&);
	void calcAM(vector<double>&, vector<double>&, vector<double>&);
	void update(const int&, const vector<double>&, const vector<double>&);
	void setInitialConditions(vector<double>&, vector<double>&);
	void setTemperature(double&);
	int setTRNumbers(int);
	void updateDofs(vector<double>&, vector<double>&);
	int setInertiaNumbers(int, vector<int>&);
	void setQatComponents(const vector<double>&, const vector<double>&);
	void setSurfAtBody(Surface* surfa)	{surface = surfa;}
//	void setLocalPointsAtBody(void)	{vLocalPoints = surface->vLocalPoints;}
	void getPointNames(vector<string>&);
	void fillMSmooth(sparseMatrix& Ma, const vector<double>& q, const double& time );
	void fillFSmooth(vector<vector<double> >&, const vector<double>&, const vector<double>&, const double&);

	int checkComponents(int);
	int setComponents();

	/** Virtual functions */
	virtual void setPTPointsComp()=0;		/** Set pointers to points in each component */
	virtual void setPTPointsLoad()=0;		/** Set pointers to points in each load */
	virtual void setPPointSurface()=0;		/** Set pointers to surface points in each component */
	virtual void setMatAtComp()=0;			/** Set pointers to material at components */
	virtual void getBoundary(vector<vector<string> >&)=0;
	virtual void writeMSH(ofstream&)=0;		/** MSH format for Gmsh */
	virtual void writeVTU(ofstream&, bool&, bool&, bool&)=0;		/** VTU format for Paraview */
	virtual void writeOOGL(ofstream&)=0;	/** OOGL format for Geomview */
	virtual void writeFileTemp(const double&, ofstream &)=0;
	virtual void setIniPosBody(vector<double>&)=0;

	/** Friend functions */
	friend void addSystemName(string& str, const string& strname);
	friend string getStringHead(const string& str);
	friend string getStringTail(const string& str);
	friend 	bool checkForSlash(const string& str);
	friend 	string subsSlash(const string& str);
};
#endif
